module TinyScheme;

import core.stdc.stdio;
import core.stdc.config;

extern (C)
{
	struct cell;
	struct scheme;

	//  alias struct scheme scheme;
	alias cell *pointer;
	
	alias void * function(size_t) func_alloc;
	alias void function(void *) func_dealloc;
	
	/* num, for generic arithmetic */
	struct num {
		char is_fixnum;
		union value {
			c_long ivalue;
			double rvalue;
		}
	}
	
	scheme* scheme_init_new();
	scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
	int scheme_init(scheme *sc);
	int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc);
	void scheme_deinit(scheme *sc);
	
	void scheme_set_input_port_file(scheme *sc, FILE *fin);
	void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end);
	
	void scheme_set_output_port_file(scheme *sc, FILE *fin);
	
	void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end);
	
	void scheme_load_file(scheme *sc, FILE *fin);
	void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename);
	void scheme_load_string(scheme *sc, const char *cmd);
	pointer scheme_apply0(scheme *sc, const char *procname);
	pointer scheme_call(scheme *sc, pointer func, pointer args);
	pointer scheme_eval(scheme *sc, pointer obj);
	
	void scheme_set_external_data(scheme *sc, void *p);
	
	void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value);

	alias pointer function(scheme *, pointer) foreign_func;

	pointer _cons(scheme *sc, pointer a, pointer b, int immutable_);
	pointer mk_integer(scheme *sc, int num);
	pointer mk_real(scheme *sc, double num);
	pointer mk_symbol(scheme *sc, const char *name);
	pointer gensym(scheme *sc);
	pointer mk_string(scheme *sc, const char *str);
	pointer mk_counted_string(scheme *sc, const char *str, int len);
	pointer mk_empty_string(scheme *sc, int len, char fill);
	pointer mk_character(scheme *sc, int c);
	pointer mk_foreign_func(scheme *sc, foreign_func f);
	void putstr(scheme *sc, const char *s);
	int list_length(scheme *sc, pointer a);
	int eqv(pointer a, pointer b);

	/+ #if USE_INTERFACE +/
	struct scheme_interface {
		void function(scheme *sc, pointer env, pointer symbol, pointer value) scheme_define;
		pointer function(scheme *sc, pointer a, pointer b) cons;
		pointer function(scheme *sc, pointer a, pointer b) immutable_cons;
		pointer function(scheme *sc, int n) reserve_cells;
		pointer function(scheme *sc, int num) mk_integer;
		pointer function(scheme *sc, double num) mk_real;
		pointer function(scheme *sc, const char *name) mk_symbol;
		pointer function(scheme *sc) gensym;
		pointer function(scheme *sc, const char *str) mk_string;
		pointer function(scheme *sc, const char *str, int len) mk_counted_string;
		pointer function(scheme *sc, int c) mk_character;
		pointer function(scheme *sc, int len) mk_vector;
		pointer function(scheme *sc, foreign_func f) mk_foreign_func;
		void function(scheme *sc, const char *s) putstr;
		void function(scheme *sc, int c) putcharacter;
		
		int function(pointer p) is_string;
		char *function(pointer p) string_value;
		int function(pointer p) is_number;
		num function(pointer p) nvalue;
		int function(pointer p) ivalue;
		double function(pointer p) rvalue;
		int function(pointer p) is_integer;
		int function(pointer p) is_real;
		int function(pointer p) is_character;
		int function(pointer p) charvalue;
		int function(scheme *sc, pointer p) is_list;
		int function(pointer p) is_vector;
		int function(scheme *sc, pointer vec) list_length;
		int function(pointer vec) vector_length;
		void function(pointer vec, pointer elem) fill_vector;
		pointer function(pointer vec, int ielem) vector_elem;
		pointer function(pointer vec, int ielem, pointer newel) set_vector_elem;
		int function(pointer p) is_port;
		int function(pointer p) is_pair;
		pointer function(pointer p) pair_car;
		pointer function(pointer p) pair_cdr;
		pointer function(pointer p, pointer q) set_car;
		pointer function(pointer p, pointer q) set_cdr;
		
		int function(pointer p) is_symbol;
		char *function(pointer p) symname;
		
		int function(pointer p) is_syntax;
 		int function(pointer p) is_proc;
 		int function(pointer p) is_foreign;
		char *function(pointer p) syntaxname;
		int function(pointer p) is_closure;
		int function(pointer p) is_macro;
		pointer function(pointer p) closure_code;
		pointer function(pointer p) closure_env;
		
		int function(pointer p) is_continuation;
		int function(pointer p) is_promise;
		int function(pointer p) is_environment;
		int function(pointer p) is_immutable;
		void function(pointer p) setimmutable;
		void function(scheme *sc, FILE *fin) load_file;
		void function(scheme *sc, const char *input) load_string;
	}

	/+ '!STANDALONE' +/
	struct scheme_registerable {
		foreign_func  f;
		char * name;
	}
	void scheme_register_foreign_func_list(scheme * sc, scheme_registerable * list, int n);
}

